﻿//-------------------------------------------------------------------------------
// <copyright file="ExtendedPermission.cs" company="TaskyMedia LLC">
//     Copyright (c) TaskyMedia LLC.
// </copyright>
//-------------------------------------------------------------------------------

/*
 * Copyright (c) 2010, TaskyMedia LLC
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 *   Redistributions of source code must retain the above copyright notice, this 
 *     list of conditions and the following disclaimer.
 *   Redistributions in binary form must reproduce the above copyright notice, this
 *     list of conditions and the following disclaimer in the documentation and/or
 *     other materials provided with the distribution.
 *   Neither the name of TaskyMedia LLC nor the names of its contributors may be used
 *   to endorse or promote products derived from this software without specific prior
 *   written permission.
 *   
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE. 
 */

namespace FBGraphApi
{
    using System;
    using System.Reflection;
    using System.Text;

    /// <summary>
    /// Specifies which extended permissions are requested by the Application.
    /// </summary>
    /// <remarks>
    /// <para>Permission XML comments and remarks retrieve from 
    /// http://developers.facebook.com/docs/authentication/permissions 
    /// as of 16 Jul 2010.</para>
    /// <para>
    /// When a Facebook user authorizes your application, your application gets
    /// access to the user's Facebook ID. By default, your application can access
    /// all public data in a user's profile, including her name, profile picture,
    /// gender, and friends. If your application needs to access other parts of
    /// the user's profile that may be private, or if your application needs to
    /// publish content to Facebook on a user's behalf, your application must request
    /// extended permissions.
    /// </para>
    /// <para>
    /// Likewise, to protect the privacy of users who have not explicitly authorized
    /// your application, your application will only be able to access the basic profile
    /// information about a user's friends, like their names and profile pictures.
    /// If your application needs to access other data about a user's friends to enable
    /// social functionality, you will need to request some of the special friends
    /// permissions.
    /// </para>
    /// </remarks>
    public enum ExtendedPermission
    {
        /*
        * 
        * Publishing Permissions
        * 
        */

        /// <summary>
        /// Enables your application to post content, comments, and likes to a
        /// user's stream and to the streams of the user's friends, without prompting
        /// the user each time.
        /// </summary>
        [ExtendedPermissionMapping("publish_stream")]
        PublishStream,

        /// <summary>
        /// Enables your application to create and modify events on the user's behalf.
        /// </summary>
        [ExtendedPermissionMapping("create_event")]
        CreateEvent,

        /// <summary>
        /// Enables your application to RSVP to events on the user's behalf.
        /// </summary>
        [ExtendedPermissionMapping("rsvp_event")]
        RsvpEvent,

        /// <summary>
        /// Enables your application to send messages to the user and respond
        /// to messages from the user via text message.
        /// </summary>
        [ExtendedPermissionMapping("sms")]
        Sms,

        /// <summary>
        /// Enables your application to perform authorized requests on behalf
        /// of the user at any time. By default, most access tokens expire after
        /// a short time period to ensure applications only make requests on behalf
        /// of the user when the are actively using the application. This permission
        /// makes the access token returned by our OAuth endpoint long-lived.
        /// </summary>
        [ExtendedPermissionMapping("offline_access")]
        OfflineAccess,

        /*
        * 
        * Page Permissions
        * 
        */

        /// <summary>
        /// Enables your application to retrieve access_tokens for pages the user
        /// administrates. The access tokens can be queried using the "accounts"
        /// connection in the Graph API. This permission is only compatible with
        /// the Graph API.
        /// </summary>
        [ExtendedPermissionMapping("manage_pages")]
        ManagePages,

        /*
        * 
        * Data Permissions
        * 
        */

        /// <summary>
        /// Provides access to the user's primary email address in the email property.
        /// Do not spam users. Your use of email must comply both with Facebook policies
        /// and with the CAN-SPAM Act.
        /// </summary>
        [ProfilePermissionMapping("email", true, "email")]
        Email,

        /// <summary>
        /// Provides read access to the Insights data for pages, applications, and
        /// domains the user owns.
        /// </summary>
        [ExtendedPermissionMapping("read_insights")]
        ReadInsights,

        /// <summary>
        /// Provides access to all the posts in the user's News Feed and enables 
        /// your application to perform searches against the user's News Feed
        /// </summary>
        [ExtendedPermissionMapping("read_stream")]
        ReadStream,

        /// <summary>
        /// Provides the ability to read from a user's Facebook Inbox. You must request
        /// to be whitelisted before you can prompt for this permission.
        /// </summary>
        [ExtendedPermissionMapping("read_mailbox")]
        ReadMailbox,

        /// <summary>
        /// Provides the ability to manage ads and call the Facebook Ads API on
        /// behalf of a user.
        /// </summary>
        [ExtendedPermissionMapping("ads_management")]
        AdsManagement,

        /// <summary>
        /// Provides applications that integrate with Facebook Chat the ability
        /// to log in users.
        /// </summary>
        [ExtendedPermissionMapping("xmpp_login")]
        XmppLogin,

        /// <summary>
        /// Provides access to the "About Me" section of the profile in the about property.
        /// </summary>
        [ProfilePermissionMapping("user_about_me", true, "about")]
        UserAboutMe,

        /// <summary>
        /// Provides access to the "About Me" section of a friend's profile in the about property.
        /// </summary>
        [ProfilePermissionMapping("friends_about_me", false, "about")]
        FriendsAboutMe,

        /// <summary>
        /// Provides access to the user's list of activities as the activities connection.
        /// </summary>
        [ExtendedPermissionMapping("user_activities")]
        UserActivities,

        /// <summary>
        /// Provides access to the user's friend's list of activities as the activities connection.
        /// </summary>
        [ExtendedPermissionMapping("friends_activities")]
        FriendsActivities,

        /// <summary>
        /// Provides access to the full birthday with year as the birthday_date property.
        /// </summary>
        [ProfilePermissionMapping("user_birthday", true, "birthday_date")]
        UserBirthday,

        /// <summary>
        /// Provides access to the friend's full birthday with year as the birthday_date property.
        /// </summary>
        [ProfilePermissionMapping("friends_birthday", false, "birthday_date")]
        FriendsBirthday,

        /// <summary>
        /// Provides access to education history as the education property.
        /// </summary>
        [ProfilePermissionMapping("user_education_history", true, "education")]
        UserEducationHistory,

        /// <summary>
        /// Provides access to the friend's education history as the education property.
        /// </summary>
        [ProfilePermissionMapping("friends_education_history", false, "education")]
        FriendsEducationHistory,

        /// <summary>
        /// Provides access to the list of events the user is attending as the
        /// events connection.
        /// </summary>
        [ExtendedPermissionMapping("user_events")]
        UserEvents,

        /// <summary>
        /// Provides access to the list of events the user's friend is attending as the
        /// events connection.
        /// </summary>
        [ExtendedPermissionMapping("friends_events")]
        FriendsEvents,
        
        /// <summary>
        /// Provides access to the list of groups the user is a member of as the
        /// groups connection.
        /// </summary>
        [ExtendedPermissionMapping("user_groups")]
        UserGroups,

        /// <summary>
        /// Provides access to the list of groups the user's friend is a member of as the
        /// groups connection.
        /// </summary>
        [ExtendedPermissionMapping("friends_groups")]
        FriendsGroups,

        /// <summary>
        /// Provides access to the user's hometown in the hometown property.
        /// </summary>
        [ProfilePermissionMapping("user_hometown", true, "hometown")]
        UserHometown,

        /// <summary>
        /// Provides access to the user's friend's hometown in the hometown property.
        /// </summary>
        [ProfilePermissionMapping("friends_hometown", false, "hometown")]
        FriendsHometown,

        /// <summary>
        /// Provides access to the user's list of interests as the interests 
        /// connection.
        /// </summary>
        [ExtendedPermissionMapping("user_interests")]
        UserInterests,

        /// <summary>
        /// Provides access to the user's friend's list of interests as the interests 
        /// connection.
        /// </summary>
        [ExtendedPermissionMapping("friends_interests")]
        FriendsInterests,

        /// <summary>
        /// Provides access to the list of all of the pages the user has liked 
        /// as the likes connection.
        /// </summary>
        [ExtendedPermissionMapping("user_likes")]
        UserLikes,

        /// <summary>
        /// Provides access to the list of all of the pages the user's friend has liked 
        /// as the likes connection.
        /// </summary>
        [ExtendedPermissionMapping("friends_likes")]
        FriendsLikes,

        /// <summary>
        /// Provides access to the user's current location as the current_location
        /// property.
        /// </summary>
        [ProfilePermissionMapping("user_location", true, "location")]
        UserLocation,

        /// <summary>
        /// Provides access to the user's friend's current location as the current_location
        /// property.
        /// </summary>
        [ProfilePermissionMapping("friends_location", false, "location")]
        FriendsLocation,

        /// <summary>
        /// Provides access to the user's notes as the notes connection.
        /// </summary>
        [ExtendedPermissionMapping("user_notes")]
        UserNotes,

        /// <summary>
        /// Provides access to the user's friend's notes as the notes connection.
        /// </summary>
        [ExtendedPermissionMapping("friends_notes")]
        FriendsNotes,

        /// <summary>
        /// Provides access to the user's online/offline presence.
        /// </summary>
        [ExtendedPermissionMapping("user_online_presence")]
        UserOnlinePresence,

        /// <summary>
        /// Provides access to the user's friend's online/offline presence.
        /// </summary>
        [ExtendedPermissionMapping("friends_online_presence")]
        FriendsOnlinePresence,

        /// <summary>
        /// Provides access to the photos the user has been tagged in
        /// as the photos connection.
        /// </summary>
        [ExtendedPermissionMapping("user_photo_video_tags")]
        UserPhotoVideoTags,

        /// <summary>
        /// Provides access to the photos the user's friend has been tagged in
        /// as the photos connection.
        /// </summary>
        [ExtendedPermissionMapping("friends_photo_video_tags")]
        FriendsPhotoVideoTags,

        /// <summary>
        /// Provides access to the photos the user has uploaded.
        /// </summary>
        [ExtendedPermissionMapping("user_photos")]
        UserPhotos,

        /// <summary>
        /// Provides access to the photos the user's friend has uploaded.
        /// </summary>
        [ExtendedPermissionMapping("friends_photos")]
        FriendsPhotos,

        /// <summary>
        /// Provides access to the user's family and personal
        /// relationships and relationship status.
        /// </summary>
        [ExtendedPermissionMapping("user_relationships")]
        UserRelationships,

        /// <summary>
        /// Provides access to the user's friend's family and personal
        /// relationships and relationship status.
        /// </summary>
        [ExtendedPermissionMapping("friends_relationships")]
        FriendsRelationships,

        /// <summary>
        /// Provides access to the user's religious and political
        /// affiliations.
        /// </summary>
        [ProfilePermissionMapping("user_religion_politics", true, "religion", "political")]
        UserReligionPolitics,

        /// <summary>
        /// Provides access to the user's friend's religious and political
        /// affiliations.
        /// </summary>
        [ProfilePermissionMapping("friends_religion_politics", false, "religion", "political")]
        FriendsReligionPolitics,

        /// <summary>
        /// Provides access to the user's most recent status message.
        /// </summary>
        [ExtendedPermissionMapping("user_status")]
        UserStatus,

        /// <summary>
        /// Provides access to the user's friend's most recent status message.
        /// </summary>
        [ExtendedPermissionMapping("friends_status")]
        FriendsStatus,

        /// <summary>
        /// Provides access to the videos the user has uploaded.
        /// </summary>
        [ExtendedPermissionMapping("user_videos")]
        UserVideos,

        /// <summary>
        /// Provides access to the videos the user's friend has uploaded.
        /// </summary>
        [ExtendedPermissionMapping("friends_videos")]
        FriendsVideos,

        /// <summary>
        /// Provides access to the user's web site URL.
        /// </summary>
        [ExtendedPermissionMapping("user_website")]
        UserWebsite,

        /// <summary>
        /// Provides access to the user's friend's web site URL.
        /// </summary>
        [ExtendedPermissionMapping("friends_website")]
        FriendsWebsite,

        /// <summary>
        /// Provides access to work history as the work property.
        /// </summary>
        [ProfilePermissionMapping("user_work_history", true, "work")]
        UserWorkHistory,

        /// <summary>
        /// Provides access to a friend's work history as the work property.
        /// </summary>
        [ProfilePermissionMapping("friend_work_history", false, "work")]
        FriendsWorkHistory,

        /// <summary>
        /// Provides read access to any friend lists the user created.
        /// A user's friends are provided as part of basic data.
        /// </summary>
        [ExtendedPermissionMapping("read_friendlists")]
        ReadFriendLists,

        /// <summary>
        /// Provides read access to the user's friend requests.
        /// </summary>
        [ExtendedPermissionMapping("read_requests")]
        ReadRequests
    }

    /// <summary>
    /// Provides functionality for converting fields to and from the associated
    /// <see cref="ExtendedPermission" />.
    /// </summary>
    public static class ExtendedPermissions
    {
        /// <summary>
        /// Gets the query string formatted list of extended permissions.
        /// </summary>
        /// <param name="permissions">The permissions requested.</param>
        /// <returns>Returns a comma-delimited list of extended permissions.</returns>
        public static string GetPermissionsQueryString(ExtendedPermission[] permissions)
        {
            StringBuilder sb = new StringBuilder();

            foreach (ExtendedPermission permission in permissions)
            {
                if (sb.Length > 0)
                {
                    sb.Append(",");
                }

                sb.Append(permission.GetPermissionName());
            }

            return sb.ToString();
        }

        /// <summary>
        /// Will get the permission name for a given <see cref="ExtendedPermission" />.
        /// </summary>
        /// <param name="value">The <see cref="ExtendedPermission" />.</param>
        /// <returns>Returns the permission name.</returns>
        internal static string GetPermissionName(this ExtendedPermission value)
        {
            // Get the type
            Type type = value.GetType();

            // Get fieldinfo for this type
            FieldInfo fieldInfo = type.GetField(value.ToString());

            // Get the attributes
            ExtendedPermissionMappingAttribute[] attribs = fieldInfo.GetCustomAttributes(
                typeof(ExtendedPermissionMappingAttribute), false) as ExtendedPermissionMappingAttribute[];

            // Return the first if there was a match.
            return attribs.Length > 0 ? attribs[0].PermissionName : String.Empty;
        }

        /// <summary>
        /// Will get the profile field name for a given <see cref="ExtendedPermission" />.
        /// If the given permission does not map to a profile field, returns
        /// an empty string.
        /// </summary>
        /// <param name="value">The <see cref="ExtendedPermission" />.</param>
        /// <returns>Returns the profile field name.</returns>
        internal static string[] GetProfileFieldNames(this ExtendedPermission value)
        {
            // Get the type
            Type type = value.GetType();

            // Get fieldinfo for this type
            FieldInfo fieldInfo = type.GetField(value.ToString());

            // Get the attributes
            ProfilePermissionMappingAttribute[] attribs = fieldInfo.GetCustomAttributes(
                typeof(ProfilePermissionMappingAttribute), false) as ProfilePermissionMappingAttribute[];

            // Return the first if there was a match.
            return attribs.Length > 0 ? attribs[0].ProfileFieldNames : null;
        }

        /// <summary>
        /// Will get the profile field name for a given <see cref="ExtendedPermission" />.
        /// If the given permission does not map to a profile field, returns
        /// an empty string.
        /// </summary>
        /// <param name="value">The <see cref="ExtendedPermission" />.</param>
        /// <returns>Returns the profile field name.</returns>
        internal static bool IsSelf(this ExtendedPermission value)
        {
            // Get the type
            Type type = value.GetType();

            // Get fieldinfo for this type
            FieldInfo fieldInfo = type.GetField(value.ToString());

            // Get the attributes
            ProfilePermissionMappingAttribute[] attribs = fieldInfo.GetCustomAttributes(
                typeof(ProfilePermissionMappingAttribute), false) as ProfilePermissionMappingAttribute[];

            // Return the first if there was a match.
            return attribs.Length > 0 ? attribs[0].IsSelf : false;
        }
    }
}
